home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
3D_GRAPH
/
G3D_CALC.C
< prev
next >
Wrap
Text File
|
1989-08-28
|
11KB
|
605 lines
/*
Copyright '89 Christopher Moll
all rights reserved
*/
#include "graph3D.h"
#include <math.h>
#ifndef _LSC3_
# include <QuickDraw.h>
# include <MemoryMgr.h>
#endif
extern Boolean useMainFunc;
extern int mainFunct[64];
extern int numMnOps;
extern Real mnConsts[30];
extern int derivFunct[64];
extern int numDerivOps;
extern Real derivConsts[30];
Real
TheFunction(x, y, z)
Real x, y, z;
{
Real stack[50];
register int i, currOp;
Real StackOp(), FuncEval(), ArithEval();
register Real *stackPtr;
int currConst = 0;
int numOps;
stackPtr = stack + 49;
if (useMainFunc)
if (numMnOps EQ 0)
return(0.0);
else
numOps = numMnOps;
else
if (numDerivOps EQ 0)
return(0.0);
else
numOps = numDerivOps;
*stackPtr = 0.0;
for (i = 0; i < numOps; i++)
{
if (useMainFunc)
currOp = mainFunct[i];
else
currOp = derivFunct[i];
if (IS_PUSH(currOp))
{
--stackPtr;
switch (currOp) {
case PUSH_X_OP:
*stackPtr = x;
break;
case PUSH_Y_OP:
*stackPtr = y;
break;
case PUSH_Z_OP:
*stackPtr = z;
break;
case PUSH_NUM_OP:
if (useMainFunc)
*stackPtr = mnConsts[currConst++];
else
*stackPtr = derivConsts[currConst++];
break;
}
}
else if (IS_FUNC(currOp))
*stackPtr = FuncEval(*stackPtr, currOp);
else
{
stackPtr[1] = ArithEval(stackPtr[1], stackPtr[0], currOp);
++stackPtr;
}
}
return(*stackPtr);
}
static
Real
ArithEval(arg1, arg2, op)
Real arg1, arg2;
int op;
{
extern int graphType;
switch (op) {
case MULT_OP:
return(arg1 * arg2);
case DIV_OP:
if (graphType EQ DERIV_GTYPE)
if (Abs(arg2) > 1e-50)
return(arg1 / arg2);
else
return(0.0);
else
return(arg1 / arg2);
case ADD_OP:
return(arg1 + arg2);
case SUBT_OP:
return(arg1 - arg2);
case MOD_OP:
return(round(arg1) MOD round(arg2));
case POWER_OP:
return(pow(arg1, arg2));
}
}
kw()
{
if (NOT(OptionDown()))
{
while(NOT(ShiftDown()));
while(ShiftDown());
}
}
es()
{
ExitToShell();
}
static
Real
FuncEval(arg, op)
Real arg;
int op;
{
switch (op) {
case NEG_OP:
return(-arg);
case EXP_OP:
return(exp(arg));
case LOG_OP:
return(log(arg));
case LOG10_OP:
return(log10(arg));
case SQ_OP:
return(SQ(arg));
case SQRT_OP:
if (arg > 0)
return(sqrt(arg));
else
return(0.0);
case SIN_OP:
return(sin(arg));
case ASIN_OP:
return(asin(arg));
case COS_OP:
return(cos(arg));
case ACOS_OP:
return(acos(arg));
case TAN_OP:
return(tan(arg));
case ATAN_OP:
return(atan(arg));
case COTAN_OP:
return(cotan(arg));
case SINH_OP:
return(sinh(arg));
case COSH_OP:
return(cosh(arg));
case TANH_OP:
return(tanh(arg));
}
}
/*-------------------------------------------------------------------------*/
extern Real *funcResults;
extern Vector *scalVectResults;
extern Point *graphPoints; /* same elements as funcResults */
extern Real startX, startY;
extern Real endX, endY;
extern Real deltaX, deltaY;
extern int numX, numY;
extern Real scale;
extern Boolean vectrsCurrent;
extern Boolean pntsCurrent;
extern Vector maxVect, minVect;
extern Point XaxisPt, YaxisPt, ZaxisPt;
extern Point Origin;
extern Real rotMatrx[3][3];
extern Rect graphRect;
extern Boolean hideSurface, useHeight;
extern Real zScale;
extern Real ceilgZ, floorZ;
SRotatePoints(cAng, sAng, plane)
register Real cAng, sAng;
int plane;
{
register long i, numElmnts;
register double temp1, temp2;
numElmnts = numX * numY;
if (plane EQ 1)
{
for (i = 0; i < numElmnts; i++)
{
temp1 = scalVectResults[i].y;
temp2 = scalVectResults[i].z;
scalVectResults[i].y = temp1 * cAng + temp2 * sAng;
scalVectResults[i].z = temp2 * cAng - temp1 * sAng;
}
}
else if (plane EQ 2)
{
for (i = 0; i < numElmnts; i++)
{
temp1 = scalVectResults[i].x;
temp2 = scalVectResults[i].z;
scalVectResults[i].x = temp1 * cAng - temp2 * sAng;
scalVectResults[i].z = temp2 * cAng + temp1 * sAng;
}
}
else if (plane EQ 3)
{
for (i = 0; i < numElmnts; i++)
{
temp1 = scalVectResults[i].x;
temp2 = scalVectResults[i].y;
scalVectResults[i].x = temp1 * cAng - temp2 * sAng;
scalVectResults[i].y = temp2 * cAng + temp1 * sAng;
}
}
else
{
for (i = 0; i < numElmnts; i++)
{
temp1 = scalVectResults[i].z;
temp2 = scalVectResults[i].y;
scalVectResults[i].z = temp1 * cAng - temp2 * sAng;
scalVectResults[i].y = temp2 * cAng + temp1 * sAng;
}
}
}
SetPoints()
{
register Real _scale;
register int xCnt, yCnt;
register long offSet;
SetNewScale();
_scale = scale;
if (hideSurface)
CheckHideView();
for (xCnt = 0; xCnt < numX; xCnt++)
for (yCnt = 0; yCnt < numY; yCnt++)
{
offSet = (long)xCnt * (long)numY + yCnt;
graphPoints[offSet].h = (int)(scalVectResults[offSet].y * _scale)
+ Origin.h;
graphPoints[offSet].v = (int)(-scalVectResults[offSet].z * _scale)
+ Origin.v;
}
GenAxes();
pntsCurrent = TRUE;
if (hideSurface AND useHeight)
SetHeightShades();
else if (hideSurface)
SetNormalShades();
}
/*************************/
Uchar *gridFace = NIL;
extern Real cosSrc, sinSrc;
extern Boolean scrnColor, colorNorms;
SetNormalShades()
{
register int xCnt, yCnt, v;
register long offSet;
Uchar VectFace();
colorNorms = scrnColor;
if (gridFace NEQ NIL)
free(gridFace);
gridFace = (Uchar *)NewPtr(sizeof(char) * (long)numX * numY);
if (MemErr)
return(FALSE);
for (xCnt = 0; xCnt < numX-1; xCnt++)
{
for (yCnt = 0; yCnt < numY-1; yCnt++)
{
offSet = (long)xCnt * (long)numY + (long)yCnt;
v = VectFace(&scalVectResults[(long)(xCnt + 1) * numY + (long)yCnt],
&scalVectResults[offSet],
&scalVectResults[(long)xCnt * numY + (long)(yCnt + 1)]);
gridFace[offSet] = v;
}
}
}
Uchar
VectFace(a, b, c)
Vector *a, *b, *c;
{
Vector side1, side2, reslt;
Real length, zCoor;
Real VectMag();
register Real temp1, temp2;
SubtVector(a, b, &side1);
SubtVector(c, b, &side2);
CrossProduct(&side1, &side2, &reslt);
temp1 = reslt.y;
temp2 = reslt.z;
reslt.y = temp1 * cosSrc + temp2 * sinSrc;
reslt.z = temp2 * cosSrc - temp1 * sinSrc;
/*if (reslt.x < 0)
return(0);
*/
length = VectMag(&reslt);
zCoor = reslt.z/length;
if (zCoor < 0)
zCoor = 0;
if (scrnColor)
zCoor = zCoor * 255.0;
else
zCoor = zCoor * 63.0;
return((Uchar)round(zCoor));
}
/* cross-product of two vectors */
CrossProduct(a, b, reslt)
register Vector *a, *b, *reslt;
{
reslt->x = a->y * b->z - a->z * b->y;
reslt->y = a->z * b->x - a->x * b->z;
reslt->z = a->x * b->y - a->y * b->x;
}
/*** Difference and sum of two vectors;
result vector can be same as a or b ***/
SubtVector(a, b, result)
register Vector *a, *b, *result;
{
result->x = a->x - b->x;
result->y = a->y - b->y;
result->z = a->z - b->z;
}
Real
VectMag(vectP)
register Vector *vectP;
{
return( sqrt( SQ(vectP->x) + SQ(vectP->y) + SQ(vectP->z) ) );
}
SetHeightShades()
{
register int xCnt, yCnt, v;
register long offSet;
Real min, max, sc;
colorNorms = scrnColor;
if (gridFace NEQ NIL)
free(gridFace);
gridFace = (Uchar *)NewPtr(sizeof(char) * (long)numX * numY);
if (MemErr)
return(FALSE);
FindFuncMaxMin(funcResults, &min, &max);
if (scrnColor)
sc = 255.0 / (max - min);
else
sc = 63.0 / (max - min);
for (xCnt = 0; xCnt < numX-1; xCnt++)
{
for (yCnt = 0; yCnt < numY-1; yCnt++)
{
offSet = (long)xCnt * (long)numY + (long)yCnt;
gridFace[offSet] = (funcResults[offSet] - min) * sc;
}
}
}
static
FindFuncMaxMin(funcList, minPtr, maxPtr)
register Real *funcList;
Real *minPtr, *maxPtr;
{
register long i, numElems;
register Real max, min, funcVal;
max = min = funcList[0];
numElems = (long)numX * (long)numY;
for (i = 1; i < numElems; i++)
{
funcVal = funcList[i];
if (funcVal > max)
max = funcVal;
else if (funcVal < min)
min = funcVal;
}
*minPtr = min;
*maxPtr = max;
}
/*************************/
SetVectrs()
{
register int xCnt, yCnt;
register long offSet;
Real ImposLimits();
register Real xValue, yValue;
register Vector *scalePtr;
Real SdeltaX;
register Real SdeltaY;
Vector pntVect;
SdeltaX = deltaX;
SdeltaY = deltaY;
scalePtr = scalVectResults;
xValue = startX;
for (xCnt = 0; xCnt < numX; xCnt++)
{
yValue = startY;
pntVect.x = xValue;
for (yCnt = 0; yCnt < numY; yCnt++)
{
offSet = (long)xCnt * (long)numY + yCnt;
pntVect.y = yValue;
pntVect.z = (ImposLimits(funcResults[offSet]));
MatrxMul(rotMatrx, &pntVect, scalePtr++);
yValue += SdeltaY;
}
xValue += SdeltaX;
}
vectrsCurrent = TRUE;
}
static
SetNewScale()
{
DoubPoint minPnt, maxPnt;
Real scaleX, scaleY;
int graphWidth, graphHeight;
DoubPoint doubOrigin;
FindMaxMin(scalVectResults, &minPnt, &maxPnt);
graphWidth = graphRect.right - graphRect.left;
graphHeight = graphRect.bottom - graphRect.top;
scaleX = (Real)(graphWidth) / (maxPnt.h - minPnt.h);
scaleY = (Real)(graphHeight) / (maxPnt.v - minPnt.v);
scale = MIN(scaleX, scaleY);
maxPnt.h = maxPnt.h * scale;
maxPnt.v = maxPnt.v * scale;
minPnt.h = minPnt.h * scale;
minPnt.v = minPnt.v * scale;
doubOrigin.h = ((graphWidth >> 1) + graphRect.left)
- ( ((maxPnt.h - minPnt.h) / 2) + minPnt.h );
doubOrigin.v = ((graphHeight >> 1) + graphRect.top)
- ( ((maxPnt.v - minPnt.v) / 2) + minPnt.v );
Origin.h = round(doubOrigin.h);
Origin.v = round(doubOrigin.v);
}
static
FindMaxMin(graphVects, minPnt, maxPnt)
register Vector *graphVects;
DoubPoint *minPnt, *maxPnt;
{
register long i, numElems;
register Real max_h, max_v;
register Real min_h, min_v;
Real vertVal;
max_h = min_h = graphVects[0].y;
max_v = min_v = -graphVects[0].z;
numElems = (long)numX * (long)numY;
for (i = 1; i < numElems; i++)
{
if (graphVects[i].y > max_h)
max_h = graphVects[i].y;
else if (graphVects[i].y < min_h)
min_h = graphVects[i].y;
vertVal = -graphVects[i].z;
if (vertVal > max_v)
max_v = vertVal;
else if (vertVal < min_v)
min_v = vertVal;
}
minPnt->h = min_h;
minPnt->v = min_v;
maxPnt->h = max_h;
maxPnt->v = max_v;
}
Real
ImposLimits(funcVal)
Real funcVal;
{
Real temp;
temp = funcVal;
if (temp > ceilgZ)
temp = ceilgZ;
else if (temp < floorZ)
temp = floorZ;
return(temp * zScale);
}
static
ExpandRect(theRect, thePoint)
register DoubRect *theRect;
register DoubPoint *thePoint;
{
if (thePoint->h < theRect->left)
theRect->left = thePoint->h;
else if (thePoint->h > theRect->right)
theRect->right = thePoint->h;
if (thePoint->v < theRect->top)
theRect->top = thePoint->v;
else if (thePoint->v > theRect->bottom)
theRect->bottom = thePoint->v;
}
#ifdef _MC68881_ /*** This function will be a macro calling ldexp() otherwise ***/
Real
mldexp(a, n)
Real a;
register int n;
{
if (n EQ 0)
return(a);
else if (n > 0)
return(a * (Real)((long)2 << (n - 1)));
else
return(a / (Real)((long)2 << -(n + 1)));
}
#endif
static
GenAxes()
{
Vector axisVect;
axisVect.x = 1000;
axisVect.y = 0;
axisVect.z = 0;
Conv3VtoPt(&axisVect, &XaxisPt);
axisVect.x = 0;
axisVect.y = 1000;
Conv3VtoPt(&axisVect, &YaxisPt);
axisVect.y = 0;
axisVect.z = 1000;
Conv3VtoPt(&axisVect, &ZaxisPt);
}